import { GraphConfigData, NodeConfig } from "@logicflow/core"
import { NodeType, Stack } from "./Stack"
import { BranchQueue } from "./branchQueue";

//描述节点的终点表
let endpoint: Record<string, string[]> = {}

//记录节点的入度
let sourcenum: Record<string, number> = {

}
let nodeDatas: Record<string, NodeConfig> = {

}


// 
const stack = new Stack();



const init = () => {
    endpoint = {};
    sourcenum = {};
    stack.clear();
    nodeDatas = {}
    nodeDatas["start"] = {
        type: "",
        x: 0,
        y: 0
    }
}

/**
 * 将logicflow数据解析为liteflow规则
 * @param data logicflow数据
 * @returns liteflow规则
 */
export const parse = (data: GraphConfigData): string => {
    init();
    if (data.nodes.length == 0) return "";
    data.nodes.forEach(item => {
        if (!item.id) return;
        nodeDatas[item.id] = item;
    })

    data.edges.forEach(edge => {
        if (!endpoint[edge.sourceNodeId]) {
            endpoint[edge.sourceNodeId] = []
        }
        endpoint[edge.sourceNodeId].push(edge.targetNodeId);


        if (sourcenum[edge.targetNodeId] === undefined) {
            sourcenum[edge.targetNodeId] = 0;
        }
        sourcenum[edge.targetNodeId]++;
    })

    //根节点数组
    const roots = data.nodes.filter(node => !sourcenum[node.id as string]);

    //添加开始虚拟节点
    endpoint["start"] = roots.map(item => item.id as string)
    roots.forEach(root => {
        sourcenum[root.id as string] = 1;
    })

    //结尾数组
    const ends = data.nodes.filter(node => !endpoint[node.id as string]);

    //添加结束虚拟
    sourcenum["end"] = ends.length;
    ends.forEach(end => {
        endpoint[end.id as string] = ["end"];
    })


    parseThenChain("start");
    return stack.lastData;
}


/**
 * 分析then链
 * @param nodeId then链的起点
 * @param defaultData 默认数据，直接添加到then中
 * @returns then的结束节点，便于继续分析
 */
const parseThenChain = (nodeId: string, defaultData: string[] = []): string => {
    stack.create();
    defaultData.forEach(item => stack.push(item));
    parseThenNode(nodeId, true);
    return stack.quit(NodeType.THEN);
}

/**
 * 分析当个的then节点
 * @param nodeId 节点id
 * @param isStart 是否是then链的起点
 * @returns 
 */
const parseThenNode = (nodeId: string, isStart: boolean = false): any => {
    const inNum: number = sourcenum[nodeId] ? sourcenum[nodeId] : 0;
    const outNum = endpoint[nodeId] ? endpoint[nodeId].length : 0;


    if (nodeId === "end") {
        stack.addEndPoint(nodeId);
        return;
    }

    //这时候一定是在when分支中（起点的入度可以大于1）
    if (inNum > 1 && !isStart) {
        stack.addEndPoint(nodeId);
        return;
    }


    //只有虚拟节点不展示
    if (nodeId !== "start") stack.push(nodeId);


    const type = nodeDatas[nodeId].type; 
    //先分析switch,因为没连接完成时出度也会是1,可能被分析为thennode
    if (type === NodeType.SWITCH) {
        stack.pop();
        const nextId = parseSwitchNode(nodeId);
        stack.push(stack.lastData);
        return parseThenNode(nextId, sourcenum[nextId] === 0);
    }else if(type ===NodeType.If ){
        stack.pop();
        const nextId = parseIfNode(nodeId);
        stack.push(stack.lastData);
        return parseThenNode(nextId,sourcenum[nextId] === 0)
    }

    //普通节点
    if (outNum == 1) {
        return parseThenNode(endpoint[nodeId][0]);
    }


    //否则为when节点
    const nextId = parseWhenNode(nodeId);
    stack.push(stack.lastData);
    return parseThenNode(nextId, sourcenum[nextId] === 0);
}


/**
 * 解析When节点
 * @param nodeId when的开始节点
 * @returns when的结束节点，便于继续分析
 */
const parseWhenNode = (nodeId: string): string => {
    stack.create();

    const end = parseBranch(nodeId);

    stack.addEndPoint(end);

    return stack.quit(NodeType.WHEN);
}


/**
 * 将各个分支依次压入栈中
 * @param nodeId
 */
const parseBranch = (nodeId: string): string => {
    //分支起点的出度，用于判断何时结束
    let outNum = endpoint[nodeId].length;
    //分支起始起点队列
    const queue = new BranchQueue();
    const endData: Record<string, string[]> = {}
    const pushData = (end: string, data: string) => {
        if (!endData[end]) endData[end] = []
        endData[end].push(data);
    }

    endpoint[nodeId].forEach((startId: string) => {
        //将空链作为已分析完的链
        if (sourcenum[startId] > 1) {
            pushData(startId, "");
            return
        }
        queue.push(startId);
    });

    while (outNum > 0) {
        const start = queue.pop() as string;
        const end = parseThenChain(start, endData[start] || []);

        pushData(end, stack.lastData);

        //当入度出度匹配时，循环退出
        if (outNum === endData[end].length) {
            queue.push(end);
            break;
        }



        if (endData[end].length === sourcenum[end]) {
            outNum -= endData[end].length - 1
            queue.push(end);
        }
    }

    const end = queue.pop() as string;
    endData[end].forEach(item => {
        stack.push(item);
    })

    sourcenum[end] -= endData[end].length - 1;
    return end;
}

/**
 * 解析switch节点
 * @param nodeId switch的判断节点
 */
const parseSwitchNode = (nodeId: string): string => {
    //当switch还未连接完成时
    if (endpoint[nodeId].length == 1) {
        stack.lastData = `SWITCH(${nodeId})`;
        return endpoint[nodeId][0];
    }

    stack.create();

    stack.push(nodeId);
    const end = parseBranch(nodeId);
    stack.addEndPoint(end);

    return stack.quit(NodeType.SWITCH);
}

const parseIfNode = (nodeId: string) => {
    stack.create();
    stack.push(nodeId);
    if(endpoint[nodeId].length!==2){
        throw new Error("IF节点必须有两个分支");
    }
    const end = parseBranch(nodeId);
    stack.addEndPoint(end);

    return stack.quit(NodeType.If);
}